home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / PROGBLER / WHIZZARD.LZH / SCRNIO.TXT < prev    next >
Text File  |  1984-07-11  |  11KB  |  304 lines

  1. File:    SCRNIO.TXT              on CLUBware Software Diskette #1
  2. Author: Stan Radzio
  3. Copyright (C) 1984. RAYHAWK AUTOMATION, N W, INC
  4.  
  5.  
  6. Introductory User Instructions:
  7.  
  8.   To use the speed-up routines (BASPRINT, COMPRINT or PRSLASHO), do
  9. the following:
  10.  
  11.     1)Bring your system up with either DOS 1.1 or DOS 2.0.
  12.  
  13.     2)Have access to the routine you need on disk.
  14.  
  15.     3)Key the name of the routine you need and press ENTER.
  16.       (For example:  BASPRINT <ENTER>)
  17.       The routine will be loaded by DOS. It will initialize itself,
  18.       and exit back to DOS, leaving itself resident. That is, it
  19.       becomes a part of DOS until the next system initialization.
  20.       If you need the routine for normal work, you should make this
  21.       invocation part of your AUTOEXEC.BAT.
  22.  
  23.     4)From now on when you invoke your application program, the newly
  24.       resident code will display data much faster.
  25.  
  26. ---------------------------------------------------------------------
  27. The rest of the this article is divided into two sections.  The first
  28. discusses some of the technical issues involved in developing the
  29. Whizzard Screen I/O Routines.  This section is probably above anyone
  30. who is not familiar with Assembly language.  The second section
  31. (which starts on Page 4) gives a detailed description of how the
  32. individual routines work.  You need to read this only if you are
  33. interested or if the above description is a little too concise.
  34. ---------------------------------------------------------------------
  35.  
  36.  
  37. Motivation For the Effort
  38.  
  39. I've seen a fair number of articles with titles such as:  "What IBM
  40. Did Right/Wrong With the PC, PC/XT, PCjr".  Several talk about the
  41. slow BIOS screen interface.  I wanted to do something about those
  42. complaints.  So, I rewrote the BIOS screen interface, a complete
  43. replacement for interrupt 10.  I squeezed every bit of speed I could
  44. out of that code.  I used faster instructions, table lookups instead
  45. of multiply instructions, twists in the logic to avoid a divide
  46. instruction, and very tight code.
  47.  
  48. What did I get for my trouble?    An 8% improvement in the TYPE command,
  49. an 11% improvement in BASICA, a 10% improvement in WORDSTAR.  We're
  50. talking about something not worth the money here.  There is a
  51. principle of Physics involved, the Conservation of Difficulty.    Given
  52. the need to support both the graphics and monochrome card, given the
  53. ability to segment the buffer on the graphics card into 4 or 8 pages,
  54. there is a certain amount of work required to setup the registers for
  55. screen I/O, and that work is a conserved quantity.
  56.  
  57. Aha, you say!  If I can't eliminate that work, what happens if I send
  58. a whole stream of characters to the screen at once instead of a single
  59. letter at a time?
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69. File:    SCRNIO.TXT                          Page 2
  70.  
  71.  
  72.  
  73. This is a great deduction on your part, Sherlock.  We can do the
  74. register setup once, then send out a whole stream of characters.  As
  75. it is now, the BIOS screen interface will only print one character at
  76. a time on the screen.  (BIOS will repeat a single character several
  77. times but this facility is not terribly useful except to blank out a
  78. line.)    There is a DOS call (AH=9) which appears to handle a stream of
  79. characters.  Actually, this call breaks the string up and sends it to
  80. BIOS a character at a time.  Speaking of this DOS call, whose idea was
  81. it to use the dollar sign ($) as the string terminator?  (Miss Marfle,
  82. please get that man on the phone and bring in my air horn.)
  83.  
  84. Besides sitting around complaining, we can respond by writing a
  85. subroutine to take the place of the missing BIOS call.    Programs that
  86. do this, like the IBM Personal Editor, are called memory mapped in
  87. some magazines.  This makes for very snappy screens for programs that
  88. you write yourself.  We have provided a set of routines that do this
  89. if you are willing to code the CALLs in your BASIC programs.  They are
  90. included on this diskette.  They were the easy part.  I also got very
  91. tired of the hassles of doing CALLs in the interpreter and created a
  92. technique to make it source-compatible with the compiler approach.
  93. This technique is also included on this diskette.
  94.  
  95. Now, what can we do for programs we have bought off the shelf?    With a
  96. little patience and a little luck, we can discover a critical area in
  97. many programs where the data to be displayed on the screen is still
  98. tied together as a string.  The program area will probably look like:
  99.  
  100.     (type A)       MOV     CX,CHAR_COUNT
  101.                MOV     SI,STRING_ADDRESS
  102.           LABEL:   LODSB              ; load a character
  103.                CALL    OUTPUT_CHAR
  104.                LOOP    LABEL
  105.  
  106. The subroutine OUTPUT_CHAR will typically PUSH CX, move a 1 into CX
  107. (display one character per call), issue an INT 10, move the cursor
  108. over one to the right, POP CX, then return.
  109.  
  110.  
  111.  
  112. The other usual layout looks like:
  113.  
  114.     (type B)       MOV     SI,STRING_ADDRESS
  115.           LABEL:   LODSB              ; load a character
  116.                OR      AL,AL
  117.                JZ      DONE
  118.                CALL    OUTPUT_CHAR
  119.                JMP     LABEL
  120.           DONE:
  121.  
  122. This piece of code operates on a string where the length is unknown
  123. but the end of the string is tagged by a zero (null).  Only someone
  124. with tapioca for brains would use a dollar sign as a terminator.
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136. File:    SCRNIO.TXT                        Page 3
  137.  
  138.  
  139. Once you find the critical piece of code within a program, you can
  140. modify the CALL OUTPUT_CHAR to call your own subroutine, or you
  141. can replace the call with an unused interrupt, like INT 68.  Your
  142. video subroutine or interrupt handler can then grab up the whole
  143. string, send it to the screen in one shot, then return to the main
  144. program with conditions set to terminate the loop (leave a 1 in CX or
  145. leave SI pointing to a 0).
  146.  
  147. On CLUBware Software Diskette #1, there are three examples of this
  148. kind of program modification - one for the BASIC Interpreter, one for
  149. Compiled BASIC programs that use BASRUN.EXE, and one for Compiled
  150. BASIC programs which do not use BASRUN.EXE.  Now we leave theory
  151. behind and enter the very complicated real world.  Real programs do
  152. not have just a type A structure or just a type B structure; most use
  153. both techniques.  For instance, the BASIC Interpreter uses type A for
  154. PRINT statements writing text and type B for error messages.  The
  155. BASIC compiler uses type A for printing character strings and type B
  156. for printing numbers.  Both the BASIC Interpreter and the compiler
  157. also have a type C structure which looks like:
  158.  
  159.     (type C)       MOV     AL,0D
  160.                CALL    OUTPUT_CHAR
  161.  
  162. to be used when putting a carriage return on the end of a line.  Both
  163. the Compiler and the Interpreter use such a weird technique for
  164. keeping track of where carriage returns have been written and where
  165. they might be needed (and when the screen should scroll) that we don't
  166. want to mess with type C.  This brings up the next point, if you
  167. replace a subroutine like OUTPUT_CHAR in someone else's program, keep
  168. a copy of the original address in your back pocket.  If you get into a
  169. situation that your replacement subroutine can't handle, you can pass
  170. the call off to the original code.
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201. File:    SCRNIO.TXT                        Page 4
  202.  
  203.  
  204. OVERVIEWS
  205.  
  206.  
  207. How BASPRINT can be used to speed up Inpterpreter PRINT statements:
  208.  
  209. 1) Execute BASPRINT to make our code resident.    (Do this once after
  210.    booting the system.)
  211.  
  212. 2) Bring up the BASIC Interpreter by invoking either: BASIC or BASICA.
  213.  
  214. 3) When BASIC clears the screen, BASPRINT intercepts the I/O and takes
  215.    this opportunity to point the interrupt vector for INT B4 to itself.
  216.  
  217. 4) The OUTPUT_CHAR subroutine for BASIC is burned into system ROM so
  218.    it can't be changed.  However, the first instruction of the
  219.    OUTPUT_CHAR subroutine is INT B4 which will allow us to intercept
  220.    the output string and speed it to the screen.
  221.  
  222. 5) When a BASIC PRINT statement executes, it will generate an INT B4.
  223.    BASPRINT will service the interrupt, intercept the output
  224.    string, put it on the screen, then nudge the stack a little so
  225.    control returns to the OUTPUT_CHAR caller with conditions set to
  226.    terminate the type A loop.
  227.  
  228. 6) The increase in PRINT speed is a function of the string length to
  229.    be displayed.  A seven-fold increase in speed is demonstrated by
  230.    the TIMEDEMO program on the CLUBware diskette.
  231.  
  232.  
  233. How COMPRINT is used to speed up PRINT Statements compiled non-/O.
  234.  
  235. 1) Execute COMPRINT to make our code resident.    (Do this once after
  236.    booting the system.)
  237.  
  238. 2) Execute your compiled and linked BASIC program.
  239.  
  240. 3) When the BASIC module, BASRUN.EXE, clears the screen, COMPRINT
  241.    intercepts the I/O and uses the break in the action to change the
  242.    first instructions of the OUTPUT_CHAR subroutine into a call to the
  243.    PRINTER subroutine inside COMPRINT.    The OUTPUT_CHAR subroutine
  244.    inside BASRUN.EXE is loaded into high memory by the initialization
  245.    code generated by the BASIC compiler and linked from BASRUN.LIB.
  246.    The exact location of OUTPUT_CHAR is a function of the amount of
  247.    memory in your machine.  COMPRINT tracks it down and modifies it
  248.    at execution time.  This is not terribly difficult since the
  249.    routine that tried to clear the screen is a near relative to
  250.    OUTPUT_CHAR (same code segment).
  251.  
  252. 4) When a BASIC PRINT executes, the control will filter down to the
  253.    OUTPUT_CHAR subroutine who will pass the string to COMPRINT for
  254.    display on the screen.
  255.  
  256. 5) COMPRINT will increase PRINT speed in the TIMEDEMO program by a
  257.    factor of eleven.
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267. File:    SCRNIO.TXT                        Page 5
  268.  
  269.  
  270.  
  271.  
  272. How PRSLASHO is used to speed up PRINT Statements compiled with /O.
  273.  
  274. There is a similar module for BASIC compiled with the /O option.  The
  275. module is called PRSLASHO and the flow of control is close to that in
  276. COMPRINT with the extra complication that the data areas accessed by
  277. PRSLASHO are not fixed relative to the BASIC library routines.    Their
  278. final position is set by the LINK command and those data areas must be
  279. located by PRSLASHO at execution time.
  280.  
  281.  
  282. Storage Requirements:
  283.  
  284. You can use all of the modules at the same time.  Execute each one
  285. after booting the system, then run the BASIC Interpreter, execute a
  286. BASIC program compiled with or without the /O option, go back to the
  287. Interpreter, whatever.    Each module uses about 1056 bytes of memory.
  288.  
  289.  
  290. Some Limitations:
  291.  
  292. 1) Modules that write directly to the screen buffer will not be sped
  293.    up.
  294.  
  295. 2) DOS 2.0 pipelining will not pick up the screen output while these
  296.    programs are running.
  297.  
  298. 3) WINDOW type packages will probably not work properly.
  299.  
  300. 4) BASPRINT will only work with the IBM versions of BASIC and BASICA.
  301.    It will not work with any version of BASIC that does not use the
  302.    IBM ROM routines. This should eliminate all other machines.
  303.  
  304.